package be.nabu.vfs.provider;

import java.io.IOException;
import java.util.Arrays;
import java.util.regex.Pattern;

import be.nabu.vfs.provider.api.Listable;
import be.nabu.vfs.provider.api.Resource;

public class ResourceUtils {
	
	public static String getPath(Resource resource) {
		// there is no parent
		if (resource.getParent() == null) {
			if (resource.getName() == null || resource.getName().equals(""))
				return "/";
			else
				return "/" + resource.getName();
		}
		else {
			String parentPath = ResourceUtils.getPath(resource.getParent());
			if (parentPath.endsWith("/"))
				parentPath = parentPath.substring(0, parentPath.length() - 1);
			return parentPath + "/" + resource.getName();
		}
	}
	
	public static Resource getChild(Listable parent, String name) throws IOException {
		for (Resource child : parent) {
			if (child.getName().equals(name))
				return child;
		}
		return null;
	}
	
	public static Resource resolve(Resource resource, String path) throws IOException {
		// an empty string is the same as "."
		if (path.equals("") || path.equals("."))
			return resource;
		// the root itself
		else if (path.equals("/"))
			return getRoot(resource);
		// an absolute path to the root of the resource
		else if (path.startsWith("/")) {
			path = path.substring(1);
			resource = getRoot(resource);
		}
		if (path.endsWith("/"))
			path = path.substring(0, path.length() - 1);
		return resolve(resource, path.split("/"), 0);
	}
	
	private static Resource resolve(Resource resource, String [] path, int counter) throws IOException {
		Resource target = null;
		// go up one
		if (path[counter].equals(".."))
			target = resource.getParent();
		else if (path[counter].equals("."))
			target = resource;
		else {
			if (!(resource instanceof Listable))
				throw new IOException("Only listable resources can have child resources, can not retrieve " + path[counter] + " from " + resource.getName() + ". Path: " + Arrays.asList(path));
			for (Resource child : ((Listable) resource)) {
				if (child.getName().equals(path[counter])) {
					target = child;
					break;
				}
			}
		}
		if (target == null || counter == path.length - 1)
			return target;
		else
			return resolve(target, path, counter + 1);
	}
	
	public static Listable getRoot(Resource resource) {
		if (resource.getParent() == null)
			return (Listable) resource;
		else
			return getRoot(resource.getParent());
	}
	
	public static boolean isRoot(Resource resource) {
		return getRoot(resource).equals(resource);
	}
	
	public static String fixWindowsPath(String path) {
		path = path.replaceAll(Pattern.quote("\\"), "/");
		// if you are using a drive letter (e.g. "c:/temp"), make a proper path out of it (e.g. "/c/temp")
		if (path.matches("^[a-zA-Z]{1}:/.*")) {
			String drive = path.replaceAll("^([a-zA-Z]{1}):/.*", "$1");
			path = "/" + drive.toLowerCase() + "/" + path.replaceAll("^[a-zA-Z]{1}:/(.*)", "$1");
		}
		return path;
	}
}
